package com.sky.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.MessageConstant;
import com.sky.constant.PasswordConstant;
import com.sky.constant.StatusConstant;
import com.sky.context.BaseContext;
import com.sky.dto.EmployeeDTO;
import com.sky.dto.EmployeeLoginDTO;
import com.sky.dto.EmployeePageQueryDTO;
import com.sky.entity.Employee;
import com.sky.exception.AccountLockedException;
import com.sky.exception.AccountNotFoundException;
import com.sky.exception.PasswordErrorException;
import com.sky.mapper.EmployeeMapper;
import com.sky.result.PageResult;
import com.sky.service.EmployeeService;
import org.mindrot.jbcrypt.BCrypt;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;

@Service
public class EmployeeServiceImpl implements EmployeeService {

    // 日志记录器
    private static final Logger log = LoggerFactory.getLogger(EmployeeServiceImpl.class);

    @Autowired
    private EmployeeMapper employeeMapper;

    @Override
    public Employee login(EmployeeLoginDTO dto) {
        String username = dto.getUsername();
        String plainPwd = dto.getPassword();

        Employee emp = employeeMapper.getByUsername(username);
        if (emp == null) throw new AccountNotFoundException("账号不存在");

        // 关键：判断当前密码是明文还是密文（明文长度6，密文长度60）
        if (emp.getPassword().length() == 6) {
            // 第一次登录：明文转密文，更新到数据库
            String bcryptPwd = BCrypt.hashpw(plainPwd, BCrypt.gensalt(10));// 明文转密文
            emp.setPassword(bcryptPwd);// 更新密码为密文
            employeeMapper.updateById(emp); // 需在Mapper加updateById方法
            System.out.println("已自动将明文密码转为BCrypt密文：" + bcryptPwd);
        } else {
            // 后续登录：密文验证
            if (!BCrypt.checkpw(plainPwd, emp.getPassword())) {
                throw new PasswordErrorException("密码错误");
            }
        }

        if (emp.getStatus() == 0) throw new AccountLockedException("账号被锁");
        return emp;
    }



    /**
     * 新增员工
     *
     * @param dto
     */
    @Override
    public void addEmp(EmployeeDTO dto) {
        //1.补全属性
        Employee emp = new Employee();
        //属性拷贝
        BeanUtils.copyProperties(dto, emp);//dto->emp
        //2.设置默认密码123456，需要加密处理
        emp.setPassword(BCrypt.hashpw(PasswordConstant.DEFAULT_PASSWORD, BCrypt.gensalt(10)));// 明文123456转密文
        //3.设置默认状态为正常
        emp.setStatus(StatusConstant.ENABLE);
        //已经在EmployeeMapper中添加了@AtuoFill注解，会自动填充创建时间、修改时间、创建人、修改人
//        emp.setCreateTime(LocalDateTime.now());
//        emp.setUpdateTime(LocalDateTime.now());
        //4.设置创建人id，从ThreadLocal获取当前登录用户id,
        //为什么要设置创建人id？
        //因为在EmployeeMapper中添加了@AtuoFill注解，会自动填充创建人id
        //为什么要设置修改人id？
        //因为在EmployeeMapper中添加了@AtuoFill注解，会自动填充修改人id
        Long currentId = BaseContext.getCurrentId();
        emp.setCreateUser(currentId);
        //已经在EmployeeMapper中添加了@AtuoFill注解，会自动填充修改人
//        emp.setUpdateUser(currentId);
        //1.调用mapper的新增方法
        employeeMapper.addEmp(emp);

    }

    /**
     * 分页查询员工---使用分页插件
     *
     * @param dto
     * @return
     */
    @Override
    public PageResult page(EmployeePageQueryDTO dto) {
        //1.设置分页参数，查第几页，每页显示多少条
        PageHelper.startPage(dto.getPage(), dto.getPageSize());
        //2.调用mapper的分页查询方法，并强转Page。
        //3.封装PageResult对象，返回
        //page对象包含了分页查询的结果，包括总记录数和当前页数据
        //为什么可以得到很多个Employee对象？
        //因为分页查询返回的是一个Page对象，Page对象包含了很多个Employee对象
        //为什么Page可以得到很多个Employee对象？
        //因为在EmployeeMapper.xml中，list方法返回的是一个Page对象，Page对象包含了很多个Employee对象
        Page<Employee> page = employeeMapper.list(dto.getName());
        //4.返回PageResult对象，包含总记录数和当前页数据
        return new PageResult(page.getTotal(), page.getResult());
    }

    /**
     * 启用或禁用员工账号
     *
     * @param status 启用或禁用状态，1为启用，0为禁用
     * @param id
     */
    @Override
    public void enableordisabled(Integer status,long id) {
        Employee employee = Employee.builder()
                .id(id)//设置id属性有值吗？有值，就更新该id的员工状态
                .status(status)//
                //已经在EmployeeMapper中添加了@AtuoFill注解，会自动填充修改时间、修改人
//                .updateTime(LocalDateTime.now())
//                .updateUser(BaseContext.getCurrentId())
                .build();//构建一个Employee对象,build()方法会根据Employee类的属性自动创建一个Employee对象,
        // builder()方法会返回一个EmployeeBuilder对象,build()方法会根据EmployeeBuilder对象的属性自动创建一个Employee对象
        employeeMapper.updatestatus(employee);
    }

    /**
     * 根据id查询员工
     *
     * @param id
     * @return
     */
    @Override
    public Employee selectById(long id) {
        Employee employee = employeeMapper.selectById(id);
        return employee;
    }
        /**
         * 更新员工信息
         * @param dto
         */
    @Override
    public void update(EmployeeDTO dto) {
        Employee employee = new Employee();
        BeanUtils.copyProperties(dto, employee);//dto->employee
        //已经在EmployeeMapper中添加了@AtuoFill注解，会自动填充修改时间、修改人
//        employee.setUpdateTime(LocalDateTime.now());
//        employee.setUpdateUser(BaseContext.getCurrentId());
        employeeMapper.updateById(employee);
    }

}
